﻿#pragma once
#include <cmath>

namespace yzrilyzr_type{
	template<int IntegerBits, int FractionalBits>
	class FixedPoint{
		public:
		using FixedType=int32_t;
		static constexpr int const FractionalMultiplier=1 << FractionalBits;

		FixedPoint() : value(0){}

		FixedPoint(double number){
			value=static_cast<FixedType>(std::round(number * FractionalMultiplier));
		}
		FixedPoint(int number){
			value=static_cast<FixedType>(number * FractionalMultiplier);
		}
		// 转换为 double
		operator double() const{
			return static_cast<double>(value) / FractionalMultiplier;
		}

		// 转换为 int
		operator int() const{
			return static_cast<int>(value / FractionalMultiplier);
		}

		// 转换为 float
		operator float() const{
			return static_cast<float>(value) / FractionalMultiplier;
		}

		// 取负数运算符
		FixedPoint operator-() const{
			FixedPoint result;
			result.value=-value;
			return result;
		}

		//赋值
		FixedPoint & operator=(double number){
			value=static_cast<FixedType>(std::round(number * FractionalMultiplier));
			return *this;
		}
		FixedPoint & operator=(int number){
			value=static_cast<FixedType>(number * FractionalMultiplier);
			return *this;
		}

		// 重载比较运算符
		bool operator<(const FixedPoint & other) const{
			return value < other.value;
		}
		bool operator<=(const FixedPoint & other) const{
			return value <= other.value;
		}
		bool operator>(const FixedPoint & other) const{
			return value > other.value;
		}
		bool operator>=(const FixedPoint & other) const{
			return value >= other.value;
		}
		bool operator==(const FixedPoint & other) const{
			return value == other.value;
		}
		bool operator!=(const FixedPoint & other) const{
			return value != other.value;
		}
		// 添加判断是否为整数的方法
		bool isInteger() const{
			return (value & (FractionalMultiplier - 1)) == 0;
		}

		//基本运算
		FixedPoint operator+(const FixedPoint & other) const{
			FixedPoint result;
			result.value=value + other.value;
			return result;
		}
		FixedPoint operator-(const FixedPoint & other) const{
			FixedPoint result;
			result.value=value - other.value;
			return result;
		}
		FixedPoint operator*(const FixedPoint & other) const{
			FixedPoint result;
			result.value=static_cast<FixedType>((static_cast<int64_t>(value) * other.value) >> FractionalBits);
			return result;
		}
		FixedPoint operator/(const FixedPoint & other) const{
			FixedPoint result;
			result.value=static_cast<FixedType>((static_cast<int64_t>(value) << FractionalBits) / other.value);
			return result;
		}
		FixedPoint & operator+=(const FixedPoint & other){
			value+=other.value;
			return *this;
		}
		FixedPoint & operator-=(const FixedPoint & other){
			value-=other.value;
			return *this;
		}
		FixedPoint & operator*=(const FixedPoint & other){
			value=static_cast<FixedType>((static_cast<int64_t>(value) * other.value) >> FractionalBits);
			return *this;
		}
		FixedPoint & operator/=(const FixedPoint & other){
			value=static_cast<FixedType>((static_cast<int64_t>(value) << FractionalBits) / other.value);
			return *this;
		}

		// 重载算术运算符以支持与int直接运算
		FixedPoint operator+(int number) const{
			return *this + FixedPoint(number);
		}
		FixedPoint operator-(int number) const{
			return *this - FixedPoint(number);
		}
		FixedPoint operator*(int number) const{
			return *this * FixedPoint(number);
		}
		FixedPoint operator/(int number) const{
			return *this / FixedPoint(number);
		}
		FixedPoint & operator+=(int number){
			return *this+=FixedPoint(number);
		}
		FixedPoint & operator-=(int number){
			return *this-=FixedPoint(number);
		}
		FixedPoint & operator*=(int number){
			return *this*=FixedPoint(number);
		}
		FixedPoint & operator/=(int number){
			return *this/=FixedPoint(number);
		}
		// 重载算术运算符以支持与double直接运算
		FixedPoint operator+(double number) const{
			return *this + FixedPoint(number);
		}
		FixedPoint operator-(double number) const{
			return *this - FixedPoint(number);
		}
		FixedPoint operator*(double number) const{
			return *this * FixedPoint(number);
		}
		FixedPoint operator/(double number) const{
			return *this / FixedPoint(number);
		}
		FixedPoint & operator+=(double number){
			return *this+=FixedPoint(number);
		}
		FixedPoint & operator-=(double number){
			return *this-=FixedPoint(number);
		}
		FixedPoint & operator*=(double number){
			return *this*=FixedPoint(number);
		}
		FixedPoint & operator/=(double number){
			return *this/=FixedPoint(number);
		}

		std::ostream & operator<<(std::ostream & os, const FixedPoint & fp){
			os << static_cast<double>(fp);
			return os;
		}

		FixedType value;
	};
}

// 实现全局的abs函数
template<int IntegerBits, int FractionalBits>
yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> abs(const yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> & fp){
	yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> result;
	typename yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits>::FixedType mask=fp.value >> (sizeof(typename yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits>::FixedType) * 8 - 1);
	result.value=(fp.value + mask) ^ mask;
	return result;
}
template<int IntegerBits, int FractionalBits>
bool isnan(const yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> & fp){
	return false;
}

// 全局重载运算符
template<int IntegerBits, int FractionalBits>
yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> operator+(int lhs, const yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> & rhs){
	return yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits>(lhs) + rhs;
}
template<int IntegerBits, int FractionalBits>
yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> operator-(int lhs, const yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> & rhs){
	return yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits>(lhs) - rhs;
}
template<int IntegerBits, int FractionalBits>
yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> operator*(int lhs, const yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> & rhs){
	return yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits>(lhs) * rhs;
}
template<int IntegerBits, int FractionalBits>
yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> operator/(int lhs, const yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> & rhs){
	return yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits>(lhs) / rhs;
}
// 全局重载运算符
template<int IntegerBits, int FractionalBits>
yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> operator+(double lhs, const yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> & rhs){
	return yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits>(lhs) + rhs;
}
template<int IntegerBits, int FractionalBits>
yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> operator-(double lhs, const yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> & rhs){
	return yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits>(lhs) - rhs;
}
template<int IntegerBits, int FractionalBits>
yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> operator*(double lhs, const yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> & rhs){
	return yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits>(lhs) * rhs;
}
template<int IntegerBits, int FractionalBits>
yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> operator/(double lhs, const yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits> & rhs){
	return yzrilyzr_type::FixedPoint<IntegerBits, FractionalBits>(lhs) / rhs;
}

typedef yzrilyzr_type::FixedPoint<7, 24> q7_24;
